package wowraidmanager.server.controller.cron.auction.admin;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;

import wowraidmanager.client.service.auction.AuctionListService;
import wowraidmanager.client.service.auction.CheckItemListService;
import wowraidmanager.client.service.auction.RealmListService;
import wowraidmanager.server.service.auction.AuctionListServiceImpl;
import wowraidmanager.server.service.auction.CheckItemListServiceImpl;
import wowraidmanager.server.service.auction.RealmListServiceImpl;
import wowraidmanager.shared.model.auction.AuctionList;
import wowraidmanager.shared.model.auction.CheckItemList;
import wowraidmanager.shared.model.auction.RealmList;
import wowraidmanager.shared.model.auction.json.Auction;
import wowraidmanager.shared.model.auction.json.AuctionData;
import wowraidmanager.shared.model.auction.json.Files;
import wowraidmanager.shared.model.auction.json.Info;
import wowraidmanager.shared.model.auction.json.Region;

public class PullJsonDataController extends Controller{

    static String BASE_URL = "http://us.battle.net/api/wow/auction/data/";

    static String REGION_ALLIANCE = "alliance";
    static String REGION_HORDE = "horde";
    static String REGION_NEUTRAL = "neutral";

    static Date DATE_NOW = new Date();

    static Date DATE_YESTARDAY = new Date(System.currentTimeMillis() - (24 * 60 * 60 * 1000));

    static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd");

    static String DATE_NOW_STRING = DATE_FORMAT.format(DATE_NOW);

    protected RealmListService realmListService = new RealmListServiceImpl();

    protected CheckItemListService checkItemListService = new CheckItemListServiceImpl();

    protected AuctionListService auctionListService = new AuctionListServiceImpl();

    ArrayList<RealmList> realmListList;

    ArrayList<CheckItemList> checkItemListList;

    ArrayList<AuctionList> auctionListList;

    ArrayList<AuctionList> setAuctionListList = new ArrayList<AuctionList>();

    @Override
    public Navigation run() throws Exception{

        long time = System.currentTimeMillis();
        getBaseData();
        setAuctionData();

        System.out.println(System.currentTimeMillis() - time);

        return null;
    }

    private void getBaseData(){
        realmListList = realmListService.getRealmList();
        checkItemListList = checkItemListService.getCheckItemList();
        auctionListList = auctionListService.getAuctionList(DATE_NOW, DATE_YESTARDAY);
    }

    private void setAuctionData(){
        if(!realmListList.isEmpty()){
            for(RealmList realmList:realmListList){
                Files files = getFilesData(realmList);
                Info info = files.getFiles().get(0);
                if(!realmList.getLastmodified().isEmpty() && realmList.getLastmodified().equals(info.getLastModified())){
                    continue;
                }else{
                    realmList.setLastmodified(info.getLastModified());
                    realmList.setUpdateTime(new Date());
                    AuctionData auctionData = getAuctionData(info.getUrl());

                    if(auctionData != null){
                        ArrayList<AuctionList> auctionListFromData = new ArrayList<AuctionList>();
                        auctionListFromData = setAuctionList(auctionData.getAlliance(), auctionListFromData, realmList, REGION_ALLIANCE);
                        auctionListFromData = setAuctionList(auctionData.getHorde(), auctionListFromData, realmList, REGION_HORDE);
                        auctionListFromData = setAuctionList(auctionData.getNeutral(), auctionListFromData, realmList, REGION_NEUTRAL);
                        setAuctionDataList(realmList, auctionListFromData);
                    }
                }
            }

            auctionListService.setAuctionList(setAuctionListList);
            realmListService.setRealmList(realmListList);
        }

    }

    private void setAuctionDataList(RealmList realmList, ArrayList<AuctionList> auctionListFromData){
        ArrayList<AuctionList> auctionListFromTable = getAuctionDataList(realmList.getRealm());

        for(AuctionList auctionFromData:auctionListFromData){
            boolean isContain = false;
            String itemId = auctionFromData.getItemId();
            for(AuctionList auctionFromTable:auctionListFromTable){
                if(auctionFromTable.getItemId().equals(itemId) && auctionFromTable.getRegion().equals(auctionFromData.getRegion())){
                    setAuctionListList.add(addAuctionData(auctionFromData, auctionFromTable));
                    isContain = true;
                    break;
                }
            }

            if(isContain == false){
                setAuctionListList.add(auctionFromData);
            }
        }
    }

    private AuctionList addAuctionData(AuctionList auctionFromDataList, AuctionList auctionFromTableList){

        for(Auction auctionFromData:auctionFromDataList.getAuctionData()){
            boolean isContain = false;
            for(Auction auctionFromTable:auctionFromTableList.getAuctionData()){
                if(auctionFromData.getAuc().equals(auctionFromTable.getAuc())){
                    isContain = true;
                    break;
                }
            }
            if(isContain == false){
                auctionFromTableList.getAuctionData().add(auctionFromData);
            }
        }
        return auctionFromTableList;
    }

    private ArrayList<AuctionList> getAuctionDataList(String realm){
        ArrayList<AuctionList> setAuctionList = new ArrayList<AuctionList>();

        for(AuctionList auctionList:auctionListList){
            if(auctionList.getRealm().equals(realm) && DATE_FORMAT.format(auctionList.getDate()).equals(DATE_NOW_STRING)){
                setAuctionList.add(auctionList);
            }
        }
        return setAuctionList;
    }

    private ArrayList<AuctionList> setAuctionList(Region region, ArrayList<AuctionList> auctionListList, RealmList realmList, String regionName){

        for(CheckItemList checkItemList:checkItemListList){
            String itemId = checkItemList.getItemId();
            ArrayList<Auction> auctionList = new ArrayList<Auction>();
            for(Auction auction:region.getAuctions()){
                if(auction.getItem().equals(itemId)){
                    auctionList.add(auction);
                }
            }

            if(!auctionList.isEmpty()){
                AuctionList auction = new AuctionList();
                auction.setAuctionData(auctionList);
                auction.setItemId(auctionList.get(0).getItem());
                auction.setRealm(realmList.getRealm());
                auction.setRegion(regionName);
                auction.setDate(DATE_NOW);
                auctionListList.add(auction);
            }
        }
        return auctionListList;
    }

    private Files getFilesData(RealmList realmList){

        ObjectMapper mapper = new ObjectMapper();
        URL url = null;
        Files files = null;
        try{
            url = new URL(BASE_URL + realmList.getRealm());
            files = mapper.readValue(url, Files.class);
        }catch(JsonParseException e){
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }catch(JsonMappingException e){
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }catch(IOException e){
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }

        return files;
    }

    private AuctionData getAuctionData(String urlString){

        ObjectMapper mapper = new ObjectMapper();
        URL url = null;
        HttpURLConnection httpConn = null;

        try{
            url = new URL(urlString);
        }catch(MalformedURLException e){
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }

        /*
         * int startpos = 0; int endpos; int seg = 1024 * 1000; int len = 1;
         * byte[] date = new byte[0]; while(len > 0){ endpos = startpos + seg;
         * try{ httpConn = (HttpURLConnection)url.openConnection();
         * httpConn.setRequestMethod("GET");
         * httpConn.setRequestProperty("User-Agent",
         * "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14"
         * );
         *
         * httpConn.setRequestProperty("Range", "bytes=" + startpos + "-" +
         * endpos); httpConn.connect(); InputStream in =
         * httpConn.getInputStream();
         *
         * len = httpConn.getContentLength(); if(len < 0){ break; } byte[] b =
         * new byte[len]; in.read(b, 0, len);
         *
         * date = addAuctionDate(date, b); startpos += len;
         * httpConn.disconnect(); }catch(IOException e){ // TODO 自動生成された catch
         * ブロック e.printStackTrace(); } }
         */

        try{
            httpConn = (HttpURLConnection)url.openConnection();
            httpConn.setRequestMethod("GET");
            httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14");
            httpConn.setConnectTimeout(10000);
            httpConn.setReadTimeout(10000);
            httpConn.connect();
            InputStream in = httpConn.getInputStream();

            return mapper.readValue(in, AuctionData.class);
            // return mapper.readValue(date, AuctionData.class);
        }catch(JsonParseException e){
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }catch(JsonMappingException e){
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }catch(IOException e){
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }finally{
            httpConn.disconnect();
        }
        return null;
    }

    /*
     * private byte[] addAuctionDate(byte[] date, byte[] b){ ByteBuffer byteBuf
     * = ByteBuffer.allocate(date.length + b.length); byteBuf.put(date);
     * byteBuf.put(b); return byteBuf.array();
     *
     * }
     */
}
